package com.ai.platform.spider.core;

import com.ai.platform.spider.core.collocate.Config;
import com.ai.platform.spider.core.collocate.Doc;
import com.ai.platform.spider.core.listener.EventListener;
import com.ai.platform.spider.logger.Logger;
import com.ai.platform.spider.logger.LoggerFactory;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;

/**
 * 功能描述 爬虫引擎
 * 创建者 yeyingsheng
 * 创建时间 2018年06月22日
 */
public class SpiderEngine<V> extends Thread implements Callable<V> {

    private Logger logger= LoggerFactory.getLogger(SpiderEngine.class);

    private Date startTime;

    private List<Spider> spiderList;

    //监听器
    private EventListener eventListener;

    private Config config;

    private int interval;

    private int threadCount;

    private CountDownLatch countDownLatch;

    private boolean loop;

    private V v;//callable 返回值

    private SpiderEngine(EventListener eventListener){
      this.eventListener=eventListener;
    }

    /**
     * 引擎创建
     * @param eventListener
     * @return
     */
    public static SpiderEngine createEngine(EventListener eventListener){
        SpiderEngine spiderEngine=new SpiderEngine(eventListener);
        spiderEngine.setName("SpiderEngine");
        return spiderEngine;
    }

    /**
     * 启动引擎
     *
     * @return SpiderEngine
     */
    public SpiderEngine startEngine() {
        start();
        return this;
    }

    /**
     * 停止引擎
     */
    public void stopEngine() {
        if (spiderList != null) {
            for (Spider spider : spiderList) {
                spider.stop();
            }
        }
        if (eventListener != null) {
            eventListener.onStop(this);
        }
    }

    /**
     * 重启引擎
     */
    public void restartEngine() {
        if (spiderList != null) {
            for (Spider spider : spiderList) {
                spider.restart();
            }
        }
        if (eventListener != null) {
            eventListener.onRestart(this);
        }
    }

    /**
     * 暂停引擎
     */
    public void pauseEngine() {
        if (spiderList != null) {
            for (Spider spider : spiderList) {
                spider.pause();
            }
        }
        if (eventListener != null) {
            eventListener.onPause(this);
        }
    }


    @Override
    public void run() {
        //读取
        if(null==config){
            logger.warn("配置参数为空");
            return;
        }
        List<Doc> docList=config.getDocs().all();
        threadCount=docList.size();
        if (threadCount <= 0) {
            threadCount = 1;
        }
        this.countDownLatch = new CountDownLatch(threadCount);
        startTime = new Date();
        spiderList = new ArrayList<>(threadCount);
        for (int i = 0; i < threadCount; i++) {
            Spider spider = new Spider(this);
            Thread thread = new Thread(spider);
            thread.start();
        }
        // 非循环模式等待线程执行完毕后关闭
        closeComplete();
    }

    /**
     * spider线程告知engine执行结束
     */
    public void notifyComplete() {
        this.countDownLatch.countDown();
    }

    /**
     * 非循环模式等待线程执行完毕后关闭
     */
    public void closeComplete() {
        if (!loop) {
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                logger.error("Interrupted error!",e);
            }
            logger.info("close SpiderEngine!");
        }

        if (eventListener != null) {
            eventListener.onStop(this);
        }
    }

    @Override
    public synchronized void start() {
        if (eventListener != null) {
            eventListener.onStart(this);
        }
        super.start();
    }


    @Override
    public V call() throws Exception {
        run();
        return v;
    }

    public V getV() {
        return v;
    }

    public void setV(V v) {
        this.v = v;
    }

    public List<Spider> getSpiderList() {
        return spiderList;
    }

    public void setSpiderList(List<Spider> spiderList) {
        this.spiderList = spiderList;
    }

    public Date getStartTime() {
        return startTime;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public Config getConfig() {
        return config;
    }

    public SpiderEngine setConfig(Config config) {
        this.config = config;
        return this;
    }

    public int getThreadCount() {
        return threadCount;
    }

    public void setThreadCount(int threadCount) {
        this.threadCount = threadCount;
    }

    public CountDownLatch getCountDownLatch() {
        return countDownLatch;
    }

    public void setCountDownLatch(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    public boolean isLoop() {
        return loop;
    }

    public void setLoop(boolean loop) {
        this.loop = loop;
    }

    public int getInterval() {
        return interval;
    }

    public void setInterval(int interval) {
        this.interval = interval;
    }
}
